#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QCryptographicHash>
#include <QObject>
#include <rsa.h>
#include <aes.h>
#include <QDir>
#include <QDebug>
#include <string.h>
#include <iostream>
#include <aes_gcm.h>
#include "diffie_hellman.h"
QString username;
QString password;
int usernum;
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    mainui_1= new mainui;
    mainui_1->tcpClient=new QTcpSocket(this);
    ui->setupUi(this);
    //需要连接服务器之后再进行登录认证
    ui->pushButton->setEnabled(true);
    ui->pushButton->setEnabled(false);
    //ui->lineIP->setText("192.168.233.135");
    //ui->lineIP->setText("127.0.0.1");
    ui->lineport->setText("5000");

    mainui_1->DH.DH_Initialize(); //生成g,p,KA
//    mainui_1->DH.g=6;
//    mainui_1->DH.p=62311;
//    mainui_1->DH.A=12783;
//    mainui_1->DH.KA=15720;
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_pushButton_clicked()//登录操作，发送登录请求
{
    QString msg;
    //发送request请求
    //判断收到的回应来确定是否能够通过
    //通过则跳转界面
    username=ui->lineEdit->text();
    password=ui->lineEdit_2->text();
    mainui_1->rsa_a.n=3425801;
    mainui_1->rsa_a.e=5327;
    mainui_1->rsa_a.d=1458263;
    //发送登录消息，包含rsa a公钥e和n，包含DH算法生成的g，p，KA
    msg="request-"+username+"-"+MD5encryption(password)+"-"+QString::number(mainui_1->rsa_a.e)+"-"+QString::number(mainui_1->rsa_a.n)+"-"+QString::number(mainui_1->DH.g)+"-"+QString::number(mainui_1->DH.p)+"-"+QString::number(mainui_1->DH.KA)+"-1-";//需要操作，服务器接收到登录请求后提取用户名和密码
    QString s=msg;
    int n=100;
    int c=n-s.length();
    int i;
    s+="-";
    for(i=0;i<c-1;i++){
        s+="1";
    }
    int l=s.length();
    qDebug()<<"msg2 length"<<s.length();
    mainui_1->tcpClient->write(s.toUtf8().toBase64());//发送的登录请求，格式是request-用户名-密码hash值-客户端rsa公钥e-客户端rsa公钥n-g-p-KA
}

void MainWindow::on_pushButton_2_clicked()//连接服务器，需要先连接服务器
{
    if(ui->pushButton_2->text()=="建立连接"){
    ui->pushButton_2->setEnabled(false);
    dis=QObject::connect(mainui_1->tcpClient, &QTcpSocket::readyRead, this, &MainWindow::ReadData);//建立连接时，绑定接收信号的槽函数是readdata
    QString address;
    address=ui->lineIP->text();
    int port;
    port=ui->lineport->text().toInt();
    mainui_1->tcpClient->connectToHost(address,port);//连接
    //等待连接成功
    if(!mainui_1->tcpClient->waitForConnected(30000))
    {
       qDebug() << "Connection failed!";
       ui->state->setText("连接失败，点击重连");
       return;
    }
    //连接成功
    qDebug() << "Connect successfully!";
    ui->state->setText("连接成功");
    ui->pushButton->setEnabled(true);//允许发送登录消息
    ui->pushButton_2->setText("关闭连接");
    return;
    }
    if(ui->pushButton_2->text()=="关闭连接"){
    mainui_1->tcpClient->disconnectFromHost();
    ui->pushButton_2->setText("建立连接");
    ui->state->setText("等待连接");
    ui->pushButton->setEnabled(false);
    return;
    }
}
void MainWindow::ReadData()
{
    //接收服务器的回应，允许登陆则跳转界面
    //设计服务器的确认消息有三种
    //允许登录消息，同时对于已经登录了的客户端是列表更新消息，ok-服务器rsa.e-rsa.n-当前用户人数（加上了这个新登录的）-用户名1-用户名2-...
    //错误提示信息，error-1- 表示在服务器的用户表中没有相应的用户名或密码的hash值不正确
    //error-2- 表示该用户已经登录了，不能重复登录
    QByteArray buffer;
        //读取缓冲区数据
    buffer = QByteArray::fromBase64(mainui_1->tcpClient->readAll());
    QString s;
    s=QString::fromUtf8(buffer);
    //qDebug()<<"s:"<<s;
    QStringList l;
    l=s.split("-");
    if(l.at(0)=="error"){
        if(l.at(1)=="1"){
        qDebug()<<"input error";
        ui->label_3->setText("服务器提示错误，请重新输入");
         QMessageBox::information(0,"infor","用户名或密码错误！");
        return;}
        else if(l.at(1)=="2"){
            qDebug()<<"repeat error";
            ui->label_3->setText("账号已经登录了，换一个");
            QMessageBox::information(0,"infor","已经登录了");
            return;
        }
    }
    if(s.startsWith(("ok-"))){//通过登录确认消息，获取服务器的公钥和n,获取当期人数和用户列表,获取KB，K
        QStringList list;
        list=s.split("-");
        int i=0;
        int l;
        QString tmp;
        list=s.split("-");
        qDebug()<<"list.at0"<<list.at(0);
        if(list.at(0)=="ok"){
            tmp=list.at(1);
            mainui_1->rsa_b.e=tmp.toInt();
            tmp=list.at(2);
            mainui_1->rsa_b.n=tmp.toInt();
            //DH Key
            QString dfkey=list.at(3);
            mainui_1->DH.KB=dfkey.toInt();
            mainui_1->DH.client_get_key();

            tmp=list.at(4);
            usernum=tmp.toInt();
            l=tmp.toInt();
            qDebug()<<"l:"<<l;
            usernum=l;
            for(i=5;i<5+l;i++){
                mainui_1->usernamelist.append(list.at(i));
            }
        qDebug()<<"length"<<tmp.toInt();
        connect(mainui_1,SIGNAL(sendsignal_1()),this,SLOT(show1()));//当退出子界面时，调用主界面的show()函数
        disconnect(dis);//退出主界面时，需要断开当前有数据可接受的信号和readdata槽函数的联系，为了在子界面mainui中绑定子界面的接收数据函数。
        mainui_1->Initialize();//调用子界面的初始化函数
        this->hide();
        mainui_1->show();
        }

    }
}
QString MainWindow::MD5encryption(QString s)
{
    QString rslt;
    rslt=QCryptographicHash::hash(s.toLatin1(),QCryptographicHash::Md5).toHex();
    return rslt;
}
void MainWindow::show1()//从mianui界面返回到登录界面调用
{
    mainui_1->tcpClient->abort();
    mainui_1->tcpClient=new QTcpSocket(this);
    mainui_1->usernamelist.clear();
    usernum=0;
    ui->pushButton_2->setText("建立连接");
    ui->pushButton_2->setEnabled(true);
    ui->state->setText("等待连接");
    ui->lineEdit->clear();
    ui->lineEdit_2->clear();
    show();
}
